#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
智能出行规划系统 - 模拟数据演示版
基于DeepSeek建议的完整实现
"""

from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import List, Optional, Dict, Tuple
import random
import json

@dataclass
class RouteLeg:
    """表示一段行程（例如，大连 -> 南京）"""
    from_city: str
    to_city: str
    transport_type: str  # 'flight', 'high_speed_rail', 'train', 'bus'
    departure_time: str  # 格式: "09:30"
    arrival_time: str    # 格式: "11:45"
    price: float
    carrier: str         # 承运商，如 CA1831, G1234
    duration: float      # 小时
    distance: float      # 公里
    comfort_score: float # 舒适度 0-10
    reliability_score: float # 可靠性 0-10

@dataclass
class TravelPlan:
    """一个完整的旅行方案，由多段RouteLeg组成"""
    legs: List[RouteLeg]
    total_price: float
    total_duration: float  # 小时
    total_distance: float  # 公里
    transfers: int
    comfort_score: float
    reliability_score: float
    optimization_score: float
    tags: List[str]
    description: str

class MockDataProvider:
    """模拟数据提供器"""
    
    def __init__(self):
        # 城市间距离数据（公里）
        self.distances = {
            ('大连', '北京'): 800, ('大连', '上海'): 1000, ('大连', '南京'): 900,
            ('大连', '合肥'): 1200, ('大连', '青岛'): 300, ('大连', '天津'): 400,
            ('大连', '沈阳'): 200, ('大连', '武汉'): 1500, ('大连', '杭州'): 1100,
            ('北京', '上海'): 1200, ('北京', '南京'): 1000, ('北京', '合肥'): 900,
            ('北京', '武汉'): 1000, ('北京', '杭州'): 1200, ('北京', '广州'): 2000,
            ('上海', '南京'): 300, ('上海', '合肥'): 400, ('上海', '杭州'): 200,
            ('上海', '武汉'): 800, ('上海', '广州'): 1200, ('上海', '深圳'): 1300,
            ('南京', '合肥'): 150, ('南京', '武汉'): 500, ('南京', '杭州'): 250,
            ('合肥', '武汉'): 400, ('合肥', '杭州'): 350, ('合肥', '南京'): 150,
            ('武汉', '广州'): 800, ('武汉', '深圳'): 900, ('武汉', '成都'): 800,
            ('杭州', '广州'): 1000, ('杭州', '深圳'): 1100, ('杭州', '南京'): 250,
        }
        
        # 交通方式配置
        self.transport_configs = {
            'flight': {
                'speed': 800,  # km/h
                'base_price_per_km': 0.8,
                'comfort_score': 8.5,
                'reliability_score': 7.0,
                'min_duration': 0.5,  # 最小0.5小时
                'carriers': ['CA', 'MU', 'CZ', '3U', '9C', 'HO']
            },
            'high_speed_rail': {
                'speed': 300,  # km/h
                'base_price_per_km': 0.4,
                'comfort_score': 9.0,
                'reliability_score': 9.5,
                'min_duration': 0.5,
                'carriers': ['G', 'D']
            },
            'train': {
                'speed': 120,  # km/h
                'base_price_per_km': 0.15,
                'comfort_score': 6.0,
                'reliability_score': 8.0,
                'min_duration': 1.0,
                'carriers': ['K', 'T', 'Z', 'Y']
            },
            'bus': {
                'speed': 80,   # km/h
                'base_price_per_km': 0.3,
                'comfort_score': 4.0,
                'reliability_score': 6.0,
                'min_duration': 2.0,
                'carriers': ['大巴', '客运']
            }
        }
        
        # 枢纽城市列表
        self.hub_cities = ['北京', '上海', '广州', '深圳', '武汉', '郑州', '西安', '南京', '杭州', '长沙', '成都', '重庆']
    
    def get_distance(self, from_city: str, to_city: str) -> float:
        """获取两城市间距离"""
        key1 = (from_city, to_city)
        key2 = (to_city, from_city)
        return self.distances.get(key1, self.distances.get(key2, 500))
    
    def generate_routes(self, from_city: str, to_city: str, transport_type: str, count: int = 3) -> List[RouteLeg]:
        """生成指定交通方式的路线"""
        distance = self.get_distance(from_city, to_city)
        config = self.transport_configs[transport_type]
        
        routes = []
        for i in range(count):
            # 生成出发时间（6:00-22:00之间）
            hour = random.randint(6, 22)
            minute = random.choice([0, 15, 30, 45])
            departure_time = f"{hour:02d}:{minute:02d}"
            
            # 计算到达时间
            duration = max(config['min_duration'], distance / config['speed'])
            arrival_hour = hour + int(duration)
            arrival_minute = minute + int((duration % 1) * 60)
            if arrival_minute >= 60:
                arrival_hour += 1
                arrival_minute -= 60
            if arrival_hour >= 24:
                arrival_hour -= 24
            arrival_time = f"{arrival_hour:02d}:{arrival_minute:02d}"
            
            # 计算价格（基础价格 + 随机波动）
            base_price = distance * config['base_price_per_km']
            price_variation = random.uniform(0.8, 1.3)
            price = round(base_price * price_variation, 0)
            
            # 生成承运商
            carrier_prefix = random.choice(config['carriers'])
            carrier_number = random.randint(1000, 9999)
            carrier = f"{carrier_prefix}{carrier_number}"
            
            # 舒适度和可靠性微调
            comfort = config['comfort_score'] + random.uniform(-0.5, 0.5)
            reliability = config['reliability_score'] + random.uniform(-0.3, 0.3)
            
            route = RouteLeg(
                from_city=from_city,
                to_city=to_city,
                transport_type=transport_type,
                departure_time=departure_time,
                arrival_time=arrival_time,
                price=price,
                carrier=carrier,
                duration=duration,
                distance=distance,
                comfort_score=round(comfort, 1),
                reliability_score=round(reliability, 1)
            )
            routes.append(route)
        
        return routes

class SmartTripPlanner:
    """智能出行规划器"""
    
    def __init__(self):
        self.data_provider = MockDataProvider()
        self.hub_cities = self.data_provider.hub_cities
    
    def find_routes(self, from_city: str, to_city: str, preference: str = 'balanced', 
                   max_transfers: int = 2) -> List[TravelPlan]:
        """主函数：查找所有可能的路线并根据偏好排序"""
        print(f"🚀 开始智能规划: {from_city} → {to_city}")
        
        all_plans = []
        
        # 1. 查找直达方案
        direct_plans = self._get_direct_plans(from_city, to_city)
        all_plans.extend(direct_plans)
        print(f"📋 找到 {len(direct_plans)} 条直达路线")
        
        # 2. 查找中转方案（智能枢纽搜索）
        transfer_plans = self._get_transfer_plans(from_city, to_city, max_transfers)
        all_plans.extend(transfer_plans)
        print(f"🔄 找到 {len(transfer_plans)} 条中转路线")
        
        # 3. 根据用户偏好排序
        optimized_plans = self._optimize_plans(all_plans, preference)
        
        # 4. 生成智能推荐
        recommended_plans = self._generate_recommendations(optimized_plans)
        
        print(f"✅ 最终推荐 {len(recommended_plans)} 条路线")
        return recommended_plans
    
    def _get_direct_plans(self, from_city: str, to_city: str) -> List[TravelPlan]:
        """获取所有直达方案（多交通工具）"""
        plans = []
        
        for transport_type in ['flight', 'high_speed_rail', 'train', 'bus']:
            routes = self.data_provider.generate_routes(from_city, to_city, transport_type, 2)
            
            for route in routes:
                plan = TravelPlan(
                    legs=[route],
                    total_price=route.price,
                    total_duration=route.duration,
                    total_distance=route.distance,
                    transfers=0,
                    comfort_score=route.comfort_score,
                    reliability_score=route.reliability_score,
                    optimization_score=0,  # 稍后计算
                    tags=['直达', transport_type],
                    description=f"{transport_type}直达，{route.duration:.1f}小时，¥{route.price}"
                )
                plans.append(plan)
        
        return plans
    
    def _get_transfer_plans(self, from_city: str, to_city: str, max_transfers: int) -> List[TravelPlan]:
        """获取通过枢纽城市中转的所有可行方案"""
        plans = []
        
        # 选择相关的中转城市
        relevant_hubs = self._select_relevant_hubs(from_city, to_city)
        print(f"🎯 中转候选城市: {relevant_hubs}")
        
        for hub_city in relevant_hubs:
            # 获取第一段行程：A -> Hub
            first_leg_options = []
            for transport_type in ['flight', 'high_speed_rail', 'train']:
                routes = self.data_provider.generate_routes(from_city, hub_city, transport_type, 1)
                first_leg_options.extend(routes)
            
            # 获取第二段行程：Hub -> B
            second_leg_options = []
            for transport_type in ['flight', 'high_speed_rail', 'train']:
                routes = self.data_provider.generate_routes(hub_city, to_city, transport_type, 1)
                second_leg_options.extend(routes)
            
            # 组合所有可行的第一段和第二段行程
            for leg1 in first_leg_options:
                for leg2 in second_leg_options:
                    # 检查中转时间是否合理
                    if self._is_valid_transfer(leg1, leg2):
                        plan = self._create_transfer_plan(leg1, leg2, hub_city)
                        if plan:
                            plans.append(plan)
        
        return plans
    
    def _select_relevant_hubs(self, from_city: str, to_city: str) -> List[str]:
        """选择相关的中转城市"""
        relevant_hubs = []
        
        # 策略1: 地理上位于两城市之间的枢纽
        for hub in self.hub_cities:
            if hub not in [from_city, to_city]:
                # 简单的地理判断：如果枢纽到两城市的距离都小于直接距离，则认为是好的中转点
                dist_to_hub = self.data_provider.get_distance(from_city, hub)
                dist_from_hub = self.data_provider.get_distance(hub, to_city)
                direct_dist = self.data_provider.get_distance(from_city, to_city)
                
                if dist_to_hub + dist_from_hub < direct_dist * 1.5:  # 允许一定绕行
                    relevant_hubs.append(hub)
        
        # 限制数量，优先选择主要枢纽
        priority_hubs = ['北京', '上海', '广州', '深圳', '武汉', '南京', '杭州']
        relevant_hubs = [h for h in priority_hubs if h in relevant_hubs] + \
                       [h for h in relevant_hubs if h not in priority_hubs]
        
        return relevant_hubs[:6]  # 最多6个中转城市
    
    def _is_valid_transfer(self, leg1: RouteLeg, leg2: RouteLeg) -> bool:
        """检查中转时间是否合理"""
        # 解析时间
        dep1_hour, dep1_min = map(int, leg1.departure_time.split(':'))
        arr1_hour, arr1_min = map(int, leg1.arrival_time.split(':'))
        dep2_hour, dep2_min = map(int, leg2.departure_time.split(':'))
        
        # 计算第一段到达时间
        arr1_time = arr1_hour * 60 + arr1_min
        dep2_time = dep2_hour * 60 + dep2_min
        
        # 计算中转时间（分钟）
        transfer_time = dep2_time - arr1_time
        if transfer_time < 0:  # 跨天情况
            transfer_time += 24 * 60
        
        # 不同交通方式的最小中转时间
        min_transfer_times = {
            'flight': 120,      # 2小时
            'high_speed_rail': 30,  # 30分钟
            'train': 60,        # 1小时
            'bus': 30           # 30分钟
        }
        
        min_time = min_transfer_times.get(leg1.transport_type, 60)
        return transfer_time >= min_time
    
    def _create_transfer_plan(self, leg1: RouteLeg, leg2: RouteLeg, hub_city: str) -> TravelPlan:
        """创建中转方案"""
        # 计算总时间和费用
        total_duration = leg1.duration + leg2.duration
        total_price = leg1.price + leg2.price
        total_distance = leg1.distance + leg2.distance
        
        # 计算平均舒适度和最低可靠性
        comfort_score = (leg1.comfort_score + leg2.comfort_score) / 2
        reliability_score = min(leg1.reliability_score, leg2.reliability_score)
        
        # 生成标签
        tags = [f'经{hub_city}中转', leg1.transport_type, leg2.transport_type]
        if leg1.transport_type != leg2.transport_type:
            tags.append('多式联运')
        
        # 生成描述
        description = f"经{hub_city}中转，{leg1.transport_type}→{leg2.transport_type}，总时长{total_duration:.1f}小时，总费用¥{total_price}"
        
        return TravelPlan(
            legs=[leg1, leg2],
            total_price=total_price,
            total_duration=total_duration,
            total_distance=total_distance,
            transfers=1,
            comfort_score=comfort_score,
            reliability_score=reliability_score,
            optimization_score=0,  # 稍后计算
            tags=tags,
            description=description
        )
    
    def _optimize_plans(self, plans: List[TravelPlan], preference: str) -> List[TravelPlan]:
        """根据用户偏好优化排序"""
        for plan in plans:
            plan.optimization_score = self._calculate_optimization_score(plan, preference)
        
        # 按优化分数排序
        return sorted(plans, key=lambda p: p.optimization_score, reverse=True)
    
    def _calculate_optimization_score(self, plan: TravelPlan, preference: str) -> float:
        """计算优化分数"""
        if preference == 'time' or preference == '时间优先':
            # 时间最短：分数与时间成反比，时间越短分数越高
            return 1000 / (1 + plan.total_duration)  # 放大系数确保时间优先
        elif preference == 'cost' or preference == '价格优先':
            # 费用最低：分数与费用成反比，费用越低分数越高
            return 1000 / (1 + plan.total_price / 50)  # 放大系数确保价格优先
        elif preference == 'comfort' or preference == '舒适度优先':
            # 舒适度最高：直接使用舒适度分数
            return plan.comfort_score * 100  # 放大系数
        else:  # balanced 或 平衡优化
            # 平衡优化：综合考虑时间、费用、舒适度
            time_score = 100 / (1 + plan.total_duration)
            cost_score = 100 / (1 + plan.total_price / 100)
            comfort_score = plan.comfort_score * 10
            reliability_score = plan.reliability_score * 10
            
            return (time_score * 0.3 + cost_score * 0.3 + 
                   comfort_score * 0.2 + reliability_score * 0.2)
    
    def _generate_recommendations(self, plans: List[TravelPlan]) -> List[TravelPlan]:
        """生成智能推荐"""
        if not plans:
            return plans
        
        # 为路线添加推荐标签
        for i, plan in enumerate(plans):
            if i == 0:
                plan.tags.append('系统推荐')
                plan.tags.append('最优方案')
            elif i == 1:
                plan.tags.append('备选方案')
            elif i == 2:
                plan.tags.append('备选方案')
            
            # 根据具体指标添加标签
            if plan.total_price < 300:
                plan.tags.append('价格优惠')
            elif plan.total_price > 800:
                plan.tags.append('价格较高')
                
            if plan.total_duration < 3:
                plan.tags.append('时间最短')
            elif plan.total_duration > 8:
                plan.tags.append('时间较长')
                
            if plan.transfers == 0:
                plan.tags.append('直达便捷')
            elif plan.transfers == 1:
                plan.tags.append('一次换乘')
            else:
                plan.tags.append('多次换乘')
                
            if '多式联运' in plan.tags:
                plan.tags.append('智能联运')
            
            # 舒适度标签
            if plan.comfort_score >= 8.5:
                plan.tags.append('高舒适度')
            elif plan.comfort_score <= 6.0:
                plan.tags.append('舒适度一般')
        
        return plans

# 演示函数
def demo_smart_planner():
    """演示智能规划系统"""
    print("🎯 智能出行规划系统演示")
    print("=" * 50)
    
    planner = SmartTripPlanner()
    
    # 测试案例1：大连到合肥
    print("\n📋 测试案例1：大连 → 合肥（平衡优化）")
    print("-" * 40)
    
    routes = planner.find_routes("大连", "合肥", "balanced", 2)
    
    print(f"\n🎯 智能规划结果:")
    for i, route in enumerate(routes[:5]):
        print(f"\n方案 {i+1}: {route.description}")
        print(f"  ⏱️  总时间: {route.total_duration:.1f}小时")
        print(f"  💰 总费用: ¥{route.total_price}")
        print(f"  🔄 换乘次数: {route.transfers}")
        print(f"  🏷️  标签: {', '.join(route.tags)}")
        print(f"  📊 优化分数: {route.optimization_score:.2f}")
        print(f"  🎯 舒适度: {route.comfort_score:.1f}/10")
        print(f"  🛡️  可靠性: {route.reliability_score:.1f}/10")
        
        # 显示交通段详情
        for j, leg in enumerate(route.legs):
            print(f"    段{j+1}: {leg.transport_type} {leg.from_city}→{leg.to_city}")
            print(f"        时间: {leg.departure_time} - {leg.arrival_time}")
            print(f"        费用: ¥{leg.price}, 时长: {leg.duration:.1f}小时")
            print(f"        承运: {leg.carrier}")
    
    # 测试案例2：不同优化类型对比
    print("\n📋 测试案例2：不同优化类型对比")
    print("-" * 40)
    
    optimizations = [
        ("time", "时间最短"),
        ("cost", "费用最低"),
        ("comfort", "舒适度最高"),
        ("balanced", "平衡优化")
    ]
    
    for opt_type, opt_name in optimizations:
        routes = planner.find_routes("北京", "上海", opt_type, 1)
        
        if routes:
            best_route = routes[0]
            print(f"\n{opt_name}:")
            print(f"  最佳方案: {best_route.description}")
            print(f"  时间: {best_route.total_duration:.1f}小时, 费用: ¥{best_route.total_price}")
            print(f"  优化分数: {best_route.optimization_score:.2f}")

if __name__ == "__main__":
    demo_smart_planner()